﻿using System;
using System.Collections.Generic;
using System.Linq;
using CccNh.Conventions;
using CccNh.Sorting;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;
using urn.nhibernate.mapping.Item2.Item2;

namespace CccNh
{
    public static class NhBootstrapper
    {
        public static Configuration GetConfiguration(string connectionString, IEnumerable<Type> entityTypes)
        {
            var cfg = new Configuration();
            var mappingXDoc = new hibernatemapping();

            var unsortedConventionTypes = typeof (IClassConvention).Assembly.GetTypesSafe()
                .Where(t => typeof (IClassConvention).IsAssignableFrom(t))
                .Where(t => t.CanBeInstantiated());
                    

            GetDependentTypes<Type> getDependentTypes = (t, potentialTypes) =>
                potentialTypes.Where(pt => typeof (IRunAfter<>).MakeGenericType(t).IsAssignableFrom(pt));

            var conventionTypes = unsortedConventionTypes.TopologicalSort(getDependentTypes);
            var conventions = conventionTypes.Select(t => (IClassConvention)Activator.CreateInstance(t)).ToList();

            foreach (var type in entityTypes)
            {
                var @class = new @class()
                {
                    name = type.AssemblyQualifiedName,
                    table = type.Name + "s",
                };
                mappingXDoc.@class.Add(@class);

            }
            foreach (var convention in conventions)
            {
                foreach (var type in entityTypes)
                {
                    var @class = mappingXDoc.@class.Single(c => c.name == type.AssemblyQualifiedName);
                    convention.Apply(type, @class, entityTypes, mappingXDoc);
                }
            }

            cfg.SetProperty(NHibernate.Cfg.Environment.Dialect, "NHibernate.Dialect.MsSql2008Dialect");
            cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.SqlClientDriver");
            cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionString, connectionString);
            cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider");
            cfg.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName);


            var xml = mappingXDoc.ToString();
            Console.WriteLine(xml);
            cfg.AddXml(xml);

            return cfg;
        }
    }
}